package com.rcadmin.core.web;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;

import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.rcadmin.busi.admin.service.SysMenuService;
import com.rcadmin.busi.admin.service.SysParamService;
import com.rcadmin.common.bean.MenuObject;
import com.rcadmin.core.app.action.ResponseData;
import com.rcadmin.core.app.service.BaseModelService;
import com.rcadmin.core.app.session.SessionControl;
import com.rcadmin.core.app.session.SessionException;
import com.rcadmin.util.DataFormat;
import com.rcadmin.util.JsonUtils;

/**
 * 
 * @author tanson lam
 * @create:2012-2-23
 */

public class BaseAction {
	protected static Logger logger = LoggerFactory.getLogger(BaseAction.class);
	private final static String SEARCH_CODE = "_QUERY";
	private final static String SEARCH_ORDER_CODE = "_ORDERBY";
	protected static final long serialVersionUID = 1L;
	@Autowired
	protected HttpServletRequest request;
	@Autowired
	protected HttpServletResponse response;
	@Autowired
	protected BaseModelService baseModelService;
	public String condition;

	@Resource
	protected SysMenuService sysMenuService;
	@Resource
	protected SysParamService sysParamService;

	protected final static Gson gson = new Gson();

	public BaseAction() {

	}

	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
		try {
			request.setCharacterEncoding("utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public void setServletResponse(HttpServletResponse response) {
		this.response = response;
		this.response.setContentType("text/html;charset=UTF-8");
	}

	public String getCondition() {
		return condition;
	}

	public void setCondition(String condition) {
		this.condition = condition;
	}

	public Integer getIntegerParameter(String key) {
		String value = request.getParameter(key);
		if (StringUtils.isEmpty(value)
				|| (value != null && value.equals("undefined")))
			return null;
		return Integer.valueOf(value);
	}

	public ModelAndView renderWithHead(String template,
			Map<String, Object> dataModel) {
		String hl = request.getParameter("hl");
		if (hl != null && !Boolean.valueOf(hl))
			dataModel.put("hl", false);
		else
			dataModel.put("hl", true);
		return render(template, dataModel);
	}

	public Integer getPage() {
		String pageStr = request.getParameter("page");
		return StringUtils.isEmpty(pageStr) ? null : Integer.valueOf(pageStr);
	}

	public Integer getPageSize() {
		String pageSizeStr = request.getParameter("pageSize");
		return StringUtils.isEmpty(pageSizeStr) ? null : Integer
				.valueOf(pageSizeStr);
	}

	private String getContextPath(HttpServletRequest request) {
		String contextPath;
		String port = request.getServerPort() == 80
				|| request.getServerPort() == 0 ? "" : ":"
				+ request.getServerPort();
		contextPath = request.getScheme() + "://" + request.getServerName()
				+ port + request.getContextPath();
		return contextPath;
	}

	public <T> ModelAndView render(String template) {
		return render(template, null);
	}

	/**
	 * 获取登陆用户ID
	 * 
	 * @return
	 * @throws SessionException
	 */
	public Integer getLoginUserId() throws SessionException {
		return SessionControl.getUserId(request);
	}

	/**
	 * 使用模板渲染
	 * 
	 * @param template
	 *            模板名稱
	 * @param dataModel
	 *            模板參數
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public <T> ModelAndView render(String template, Map<String, T> dataModel) {
		if (dataModel == null)
			dataModel = Maps.newHashMap();

		dataModel.put("contextPath", (T) getContextPath(request));
		// 模板中传入session值
		HttpSession session = request.getSession();
		String[] sessionName = session.getValueNames();
		for (String name : sessionName) {
			dataModel.put(name, (T) request.getSession().getAttribute(name));
		}
		// 模板中传入request值
		Map<?, ?> paramMap = request.getParameterMap();
		for (Iterator<?> itor = paramMap.keySet().iterator(); itor.hasNext();) {
			Object key = itor.next();
			Object object = paramMap.get(key);
			if (key instanceof String && object != null) {

				if (object.getClass().isArray()) {
					Object[] sValue = (Object[]) object;
					String value = sValue[0].toString();
					if (value.trim().isEmpty())
						continue;
					dataModel.put(key.toString(), (T) value);
				}
			}

		}
		List<MenuObject> menuList = sysMenuService.queryModuleTree();
		dataModel.put("menuList", (T) menuList);
		return new ModelAndView(template, dataModel);
	}

	public String bulidConditionSql() {
		StringBuffer sql = new StringBuffer();
		Map<String, String> queryMap = new HashMap<String, String>();
		Map<String, String[]> paramMap = request.getParameterMap();
		for (Iterator<String> itor = paramMap.keySet().iterator(); itor
				.hasNext();) {
			Object key = itor.next();
			Object object = paramMap.get(key);
			if (key instanceof String && key.toString().startsWith(SEARCH_CODE)
					&& object != null) {
				String queryKey = String.valueOf(key).substring(
						SEARCH_CODE.length());
				if (object.getClass().isArray()) {
					Object[] sValue = (Object[]) object;
					String value = sValue[0].toString();
					if (value.trim().isEmpty())
						continue;
					queryMap.put(queryKey, value);
				}

			}
			if (key instanceof String
					&& key.toString().startsWith(SEARCH_ORDER_CODE)
					&& object != null) {
				if (object.getClass().isArray()) {
					Object[] sValue = (Object[]) object;
					String value = sValue[0].toString();
					if (value.trim().isEmpty())
						continue;
				}
			}
		}
		String queryMapSql = baseModelService.buildSQLWhere(queryMap);
		if (!StringUtils.isEmpty(condition)) {
			sql.append(condition);
		}
		if (!StringUtils.isEmpty(queryMapSql)) {
			sql.append(queryMapSql);
		}

		return sql.toString();
	}

	public String bulidOrderBySql() {
		String orderSql = "";
		Map<String, String[]> paramMap = request.getParameterMap();
		for (Iterator<String> itor = paramMap.keySet().iterator(); itor
				.hasNext();) {
			Object key = itor.next();
			Object object = paramMap.get(key);

			if (key instanceof String
					&& key.toString().startsWith(SEARCH_ORDER_CODE)
					&& object != null) {
				if (object.getClass().isArray()) {
					Object[] sValue = (Object[]) object;
					String value = sValue[0].toString();
					if (value.trim().isEmpty())
						continue;
					orderSql = value;
				}
			}
		}
		return orderSql;
	}

	/**
	 * 分页url
	 * 
	 * @param paginationUrl
	 * @return
	 */
	public String getPaginationUrl(String paginationUrl) {
		String url = request.getContextPath()
				+ (paginationUrl.startsWith("/") ? paginationUrl : "/"
						+ paginationUrl);
		return url.indexOf("?") > -1 ? url : url + "?aqwertyu=123";
	}

	/**
	 * 从页面拷贝数据值到dao中.
	 * 
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	@SuppressWarnings("unchecked")
	public <T> T buildPageData(Object entityBean)
			throws IllegalArgumentException, IllegalAccessException {
		Field[] fields = entityBean.getClass().getDeclaredFields();
		Map<String, String[]> paramMap = request.getParameterMap();
		for (Field f : fields) {
			f.setAccessible(true);
			String fieldType = f.getType().getName();
			String fName = f.getName();
			if (!paramMap.containsKey(fName))
				continue;
			Object fValue = paramMap.get(fName);
			if (fValue.getClass().isArray()) {

				Object[] sValue = (Object[]) fValue;
				String value = sValue[0].toString();
				// If empty ,set null to field.
				if (value.trim().isEmpty())
					f.set(entityBean, null);
				if (value.trim().isEmpty())
					continue;
				if (fieldType.equals("java.lang.String")) {
					f.set(entityBean, value);
				} else if (fieldType.equals("java.lang.Integer")
						|| fieldType.equals("int")) {
					f.set(entityBean, Integer.valueOf(value));
				} else if (fieldType.equals("java.lang.Float")
						|| fieldType.equals("float")) {
					f.set(entityBean, Float.valueOf(value));
				} else if (fieldType.equals("java.util.Date")) {
					if (value.length() == 10) {
						f.set(entityBean, DataFormat.stringToDate(value,
								DataFormat.DATE_FORMAT));
					} else if (value.length() == 19) {
						f.set(entityBean, DataFormat.stringToDate(value,
								DataFormat.DATETIME_FORMAT));
					}
				} else if (fieldType.equals("java.sql.Timestamp")) {
					if (value.length() == 10) {
						f.set(entityBean, new java.sql.Timestamp(DataFormat
								.stringToDate(value, DataFormat.DATE_FORMAT)
								.getTime()));
					} else if (value.length() == 19) {
						f.set(entityBean,
								new java.sql.Timestamp(DataFormat.stringToDate(
										value, DataFormat.DATETIME_FORMAT)
										.getTime()));
					}
				}

			}
		}
		return (T) entityBean;
	}

	@SuppressWarnings("unchecked")
	protected <T> T getParamJson(Class<T> clazz) throws Exception {
		RequestJson<T> requestJson = null;
		if (request.getMethod().equalsIgnoreCase("POST"))
			requestJson = JsonUtils.toObject(
					IOUtils.toString(request.getInputStream()),
					RequestJson.class, clazz);
		else if (request.getMethod().equalsIgnoreCase("GET")) {
			requestJson = JsonUtils.toObject(request.getParameter("param"),
					RequestJson.class, clazz);
		}
		if (null != requestJson) {
			return requestJson.getData();
		} else {
			return null;
		}

	}

	/**
	 * 返回組裝的JSON信息到页面
	 * 
	 * @param responseData
	 */
	protected void outJsonpResult(ResponseData responseData) {
		if (responseData == null)
			throw new IllegalArgumentException(
					"responseData should not be null");
		try {
			response.setContentType("text/json;charset=utf-8");
			if (isJsonpRequest()) {
				AjaxJsonpUtils.outJson(request, response,
						JsonUtils.toJson(responseData));
			} else {
				String json = gson.toJson(responseData);
				response.getWriter().write(json);
			}

		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 是否是jsonpa请求
	 * 
	 * @param request
	 * @return
	 * @author Joeson
	 */
	private boolean isJsonpRequest() {
		if (null == request) {
			logger.error("request can not be null");
			return false;
		}

		if (!StringUtils.isEmpty(request.getParameter("callbackparam")))
			return true;
		return false;
	}
}
